/*
 * 
 */
package com.yuanmei.stockeyes.charts;

import android.content.Context;
import android.graphics.Color;
import android.graphics.PointF;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.View;
import android.view.View.OnTouchListener;

import com.tictactec.ta.lib.Core;
import com.tictactec.ta.lib.MInteger;
import com.tictactec.ta.lib.RetCode;
import com.yuanmei.stockeyes.R;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import cn.limc.androidcharts.entity.DateValueEntity;
import cn.limc.androidcharts.entity.LineEntity;
import cn.limc.androidcharts.event.IDisplayCursorListener;
import cn.limc.androidcharts.view.SlipMinusLineChart;

//import android.util.Log;

public class TalibDmaChart implements ITalibChart {
    private final Core mTaLibCore = new Core();
    private Context mContext;
    private SlipMinusLineChart mDmaChartView;
    private static final String TAG = TalibDmaChart.class.getName();

    private List<DateValueEntity> mDiffDateValueList;
    private List<DateValueEntity> mAmaDateValueList;

    private LineEntity<DateValueEntity> mDiffLineEntity;
    private LineEntity<DateValueEntity> mAmaLineEntity;

    private int mDmaSlowDiffPeriod = 50;
    private int mDmaFastDiffPeriod = 10;
    private int mDmaAmaPeriod       = 10;
    private String mDmaSlowDiffPeriodName;
    private String mDmaFastDiffPeriodName;
    private String mDmaAmaPeriodName;

    private int mTaIdxDataSetsBegin;
    private int mTaIdxDataSetsNumber;

    public TalibDmaChart(Context context) {
        mDmaChartView = new SlipMinusLineChart(context);
        TalibChartFactory.commonInitGridChart(mDmaChartView);
        TalibChartFactory.commonInitSlipLineChart(mDmaChartView);
        //TalibChartFactory.commonInitSlipStickChart(mDmaChartView);
        mContext =  mDmaChartView.getContext();
        mDmaSlowDiffPeriodName = mContext.getString(R.string.param_long_period);
        mDmaFastDiffPeriodName = mContext.getString(R.string.param_short_period);
        mDmaAmaPeriodName = mContext.getString(R.string.param_AMA_period);
    }

    @Override
    public List<Map<String, Object>> getTaParamsList() {

        List<Map<String, Object>> outParamsList = new ArrayList<Map<String, Object>>();
        Map<String, Object> item = new HashMap<String, Object>();
        item.put(ITalibChart.ITaParamNameKey,  mDmaSlowDiffPeriodName);
        item.put(ITalibChart.ITaParamValueKey, mDmaSlowDiffPeriod);
        outParamsList.add(item);

        item = new HashMap<String, Object>();
        item.put(ITalibChart.ITaParamNameKey,  mDmaFastDiffPeriodName);
        item.put(ITalibChart.ITaParamValueKey, mDmaFastDiffPeriod);
        outParamsList.add(item);

        item = new HashMap<String, Object>();
        item.put(ITalibChart.ITaParamNameKey,  mDmaAmaPeriodName);
        item.put(ITalibChart.ITaParamValueKey, mDmaAmaPeriod);
        outParamsList.add(item);

        return outParamsList;
    }

    @Override
    public void setTaParams(Hashtable<String, Integer> inParamMaps) {
         if (inParamMaps.containsKey(mDmaSlowDiffPeriodName)
                 && inParamMaps.containsKey(mDmaFastDiffPeriodName)
                 && inParamMaps.containsKey(mDmaAmaPeriodName)
                 ) {
             mDmaSlowDiffPeriod = inParamMaps.get(mDmaSlowDiffPeriodName);
             mDmaFastDiffPeriod = inParamMaps.get(mDmaFastDiffPeriodName);
             mDmaAmaPeriod = inParamMaps.get(mDmaAmaPeriodName);
        }
    }

    @Override
    public boolean reloadData(int dataLen,
                              float[] openPrices,
                              float[] highPrices,
                              float[] lowPrices,
                              float[] closePrices,
                              float[] volumes,
                              float[] amounts,
                              int[] dates) {
        MInteger fastOutBegIdx    = new MInteger();
        MInteger fastOutNBElement = new MInteger();
        double[] fastOutSMA       = new double[dataLen];
        MInteger slowOutBegIdx    = new MInteger();
        MInteger slowOutNBElement = new MInteger();
        double[] slowOutSMA       = new double[dataLen];

        RetCode retCode = mTaLibCore.sma(0, closePrices.length - 1, closePrices,
                mDmaFastDiffPeriod, fastOutBegIdx, fastOutNBElement, fastOutSMA);
        if (retCode != RetCode.Success) {
            Log.e(TAG, "DMA Chart mTaLibCore.SMA slow calc error retCode="
                    + retCode);
            return false;
        }

        retCode = mTaLibCore.sma(0, closePrices.length - 1, closePrices,
                mDmaSlowDiffPeriod, slowOutBegIdx, slowOutNBElement, slowOutSMA);
        if (retCode != RetCode.Success) {
            Log.e(TAG, "DMA Chart mTaLibCore.SMA fast calc error retCode="
                    + retCode);
            return false;
        }

        int      diffStartIndex = slowOutBegIdx.value;
        int      fastValidStart = slowOutBegIdx.value - fastOutBegIdx.value;
        int      diffNumber     = slowOutNBElement.value;
        double[] diffs          = new double[diffNumber];

//        Log.i(TAG, String.format("DMA compute sma_slow:[%d - %d], sma_fast:[%d - %d] fastValidStart=%d dataLen=%d",
//                slowOutBegIdx.value, slowOutNBElement.value,
//                fastOutBegIdx.value, fastOutNBElement.value,
//                fastValidStart,
//                dataLen));

        mDiffDateValueList = new ArrayList<>();
        for (int i = 0; i < dataLen; i++) {
            if (i < diffStartIndex) {
                mDiffDateValueList.add(new DateValueEntity(
                        (float) (fastOutSMA[0 + fastValidStart] - slowOutSMA[0]), dates[i]));
            } else {
                int idx = i - diffStartIndex;
                diffs[idx] = fastOutSMA[idx + fastValidStart] - slowOutSMA[idx];
                mDiffDateValueList.add(new DateValueEntity(
                        (float) (diffs[idx]), dates[i]));
            }
        }

        MInteger amaBegIdx    = new MInteger();
        MInteger amaNBElement = new MInteger();
        double[] amaOutSma    = new double[slowOutNBElement.value];
        retCode = mTaLibCore.sma(0, diffNumber - 1, diffs,
                mDmaAmaPeriod, amaBegIdx, amaNBElement, amaOutSma);
        if (retCode != RetCode.Success) {
            Log.e(TAG, "DMA Chart compute AMA error retCode="
                    + retCode);
            return false;
        }

        int amaStartIndex = diffStartIndex + amaBegIdx.value;
//        Log.i(TAG, String.format("DMA compute ama:[%d - %d] amaStartIndex=%d diffs.length=%d",
//                amaBegIdx.value, amaNBElement.value, amaStartIndex, diffs.length));

        mAmaDateValueList = new ArrayList<>();
        for (int i = 0; i < dataLen; i++) {
            if (i < amaStartIndex) {
                mAmaDateValueList.add(new DateValueEntity(
                        (float) (amaOutSma[0]), dates[i]));
            } else {
                int idx = i - amaStartIndex;
                mAmaDateValueList.add(new DateValueEntity(
                        (float) (amaOutSma[idx]), dates[i]));
            }
        }

        List<LineEntity<DateValueEntity>> lines = new ArrayList<LineEntity<DateValueEntity>>();

        mDiffLineEntity = new LineEntity<DateValueEntity>();
        mDiffLineEntity.setTitle("DIF");
        mDiffLineEntity.setLineColor(Color.BLUE);
        mDiffLineEntity.setLineData(mDiffDateValueList);
        lines.add(mDiffLineEntity);

        mAmaLineEntity = new LineEntity<DateValueEntity>();
        mAmaLineEntity.setTitle("AMA");
        mAmaLineEntity.setLineColor(Color.YELLOW);
        mAmaLineEntity.setLineData(mAmaDateValueList);
        lines.add(mAmaLineEntity);

        mDmaChartView.setLinesData(lines);

        mTaIdxDataSetsBegin  = amaStartIndex;
        mTaIdxDataSetsNumber = amaNBElement.value;
        return true;
    }

    @Override
    public int getTaIndexNumber() {
        return mTaIdxDataSetsNumber;
    }

    @Override
    public String getTaIndexParms() {
        return  mDmaSlowDiffPeriod
                + "," + mDmaFastDiffPeriod
                + "," + mDmaAmaPeriod;
    }

    @Override
    public String getTaIndexShortName() {
        return "DMA";
    }

    @Override
    public Spanned getTaIndexDetail() {
        if (null == mDiffDateValueList || null == mAmaDateValueList) {
            return new SpannableString("----");
        }
        int index = mDmaChartView.getSelectedIndex();

        DateValueEntity difEntity = mDiffDateValueList.get(index);
        DateValueEntity amaEntity = mAmaDateValueList.get(index);
        String          difText   = String.format(Locale.ENGLISH, "DIF:%.2f ", difEntity.getValue());
        String          amaText   = String.format(Locale.ENGLISH, "AMA:%.2f ", amaEntity.getValue());
        String          dateText  = String.format(Locale.ENGLISH, "%d ", amaEntity.getDate());

        String    finalString = difText + amaText + dateText;
        Spannable sb          = new SpannableString(finalString);

        sb.setSpan(new ForegroundColorSpan(mDiffLineEntity.getLineColor()), finalString.indexOf(difText),
                finalString.indexOf(difText) + difText.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
        sb.setSpan(new ForegroundColorSpan(mAmaLineEntity.getLineColor()), finalString.indexOf(amaText),
                finalString.indexOf(amaText) + amaText.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
        sb.setSpan(new ForegroundColorSpan(Color.GRAY), finalString.indexOf(dateText),
                finalString.indexOf(dateText) + dateText.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);

        return (sb);
    }

    @Override
    public int getTaIndexBegin() {
        return mTaIdxDataSetsBegin;
    }

    @Override
    public View getChartView() {
        return mDmaChartView;
    }

    @Override
    public void setDisplayFrom(int from) {
        mDmaChartView.setDisplayFrom(from);
    }

    @Override
    public void setDisplayCrossXOnTouch(boolean displayCrossXOnTouch) {
        mDmaChartView.setDisplayCrossXOnTouch(displayCrossXOnTouch);
    }

    @Override
    public void setDisplayNumber(int number) {
        mDmaChartView.setDisplayNumber(number);
    }

    @Override
    public void setOnTouchListener(OnTouchListener l) {
        mDmaChartView.setOnTouchListener(l);
    }

    @Override
    public void setOnDisplayCursorListener(
            IDisplayCursorListener l) {
        mDmaChartView.setOnDisplayCursorListener(l);
    }

    @Override
    public PointF getTouchPoint() {
        return mDmaChartView.getTouchPoint();
    }

    @Override
    public void setTouchPoint(PointF touchPoint) {
        mDmaChartView.setTouchPoint(touchPoint);
    }

    @Override
    public void postInvalidate() {
        mDmaChartView.postInvalidate();
    }

    @Override
    public float getValidMiddleY() {
        return mDmaChartView.getValidMiddleY();
    }
}
